package com.yixin.ystartlibrary.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Environment;
import android.text.TextUtils;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.yixin.ystartlibrary.R;


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;

/**
 * 加载图片
 */
public class ImageUtil {

    private static final String FB_IMAGE_NAME = "_fb_lckj_image_";

    private static RequestOptions mOptions = new RequestOptions()
            .placeholder(R.color.lighter_gray)
            .error(R.color.lighter_gray);

    public static void displayPic(Context context, String url, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .placeholder(R.mipmap.default_pictrue_ic)
                .error(R.mipmap.default_pictrue_ic);
        LogUtils.e(url);
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);
    }

    public static void displayDefault(Context context, String url, ImageView imageView) {
        LogUtils.e(url);
        Glide.with(context)
                .load(url)
                .apply(mOptions)
                .into(imageView);
    }

    public static void displayFreedom(Context context, String url, ImageView imageView) {
        LogUtils.e(url);
        Glide.with(context)
                .load(url)
                .apply(mOptions)
                .into(imageView);
    }

    public static void displayRound(Context context, String url, int dp, ImageView imageView) {
        LogUtils.e(url);
        RequestOptions options = new RequestOptions()
                .placeholder(R.color.lighter_gray)
                .error(R.color.lighter_gray)
                .transform(new GlideRoundTransform(context));
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);
    }

    public static void displayCircle(Context context, String url, ImageView imageView) {
        LogUtils.e(url);
        RequestOptions options = new RequestOptions()
                .placeholder(R.color.lighter_gray)
                .error(R.color.lighter_gray)
                .transform(new GlideCircleTransform(context));
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);
    }

    public static void displayDiskCenter(Context context, String file, ImageView imageView) {
        LogUtils.e(file);
        Glide.with(context)
                .load("file://" + file)
                .apply(mOptions)
                .into(imageView);
    }

    public static void displayDisk(Context context, String file, ImageView imageView) {
        LogUtils.e(file);
        Glide.with(context)
                .load("file://" + file)
                .apply(mOptions)
                .into(imageView);
    }

    public static void displayDiskFreedom(Context context, String file, ImageView imageView) {
        LogUtils.e(file);
        Glide.with(context)
                .load("file://" + file)
                .apply(mOptions)
                .into(imageView);
    }

    public static void displayResource(Context context, int resourceId, ImageView imageView) {
        Glide.with(context)
                .load(resourceId)
                .apply(mOptions)
                .into(imageView);
    }

    public static String getImageFileNewName(String imageUrl) {
        if (TextUtils.isEmpty(imageUrl)) {
            return null;
        }
        StringBuilder sb = new StringBuilder(imageUrl);
        sb.insert(imageUrl.length() - 5, "_upload_fb_new_");
        return sb.toString();
    }

    /**
     * 压缩图片.
     *
     * @param imageUrl 本地图片路径
     * @param maxSize  压缩大小
     * @param callback 压缩完成回调
     */
    public static void compressImage(final Context context, String imageUrl,
                                     final int maxSize, Consumer<String> callback) {
        Observable.just(imageUrl)
                .map(new Function<String, String>() {
                    @Override
                    public String apply(@NonNull String s) throws Exception {
                        File file = new File(s);
                        String outPath = Environment.getExternalStorageDirectory().getPath() + "/" +
                                context.getPackageName() + "/" + file.getName();
                        //判断是否已经有图片
                        File imageFile = new File(outPath);
                        if (imageFile.exists()) {
                            return outPath;
                        } else {
                            final boolean mkdirs = imageFile.mkdirs();
                            if (mkdirs) {
                                LogUtils.e("创建图片文件成功");
                            }
                        }

                        //压缩
                        try {
                            final Bitmap bitmapOrg = BitmapFactory.decodeFile(s);
                            ByteArrayOutputStream os = ImageUtil.compressAndGenImage(bitmapOrg, maxSize);
                            ImageUtil.saveBitmap(os, outPath);
                            return outPath;
                        } catch (IOException e) {
                            LogUtils.e("压缩失败 :" + e.toString());
                            return null;
                        }
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(callback);
    }

    /**
     * 图片裁剪,按照长宽短的一边为准,取中间正方形.
     */
    public static Bitmap getImageCenterCrop(String file) {
        final Bitmap bitmapOrg = BitmapFactory.decodeFile(file);
        int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();

        if (width == height) {
            return bitmapOrg;
        }

        final int START_X;
        final int START_Y;
        final int TAILOR_SIZE;

        if (width < height) {
            START_X = 0;
            START_Y = (height - width) / 2;
            TAILOR_SIZE = width;
        } else {
            START_X = (width - height) / 2;
            START_Y = 0;
            TAILOR_SIZE = height;
        }

        Bitmap newBitmap = Bitmap.createBitmap(bitmapOrg, START_X, START_Y, TAILOR_SIZE,
                TAILOR_SIZE, null, false);
        bitmapOrg.recycle();
        return newBitmap;
    }

    /**
     * 按大小缩放图片.
     */
    public static Bitmap zoomImage(Bitmap bm, int newWidth, int newHeight) {
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
    }

    /**
     * 图片压缩.
     *
     * @param maxSize 压缩大小,单位KB.
     */
    public static ByteArrayOutputStream compressAndGenImage(Bitmap bitmap, int maxSize) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        // scale
        int options = 100;
        // Store the bitmap into output stream(no compress)
        bitmap.compress(Bitmap.CompressFormat.JPEG, options, os);

        if (os.toByteArray().length / 1024 <= maxSize) {
            return os;
        }

        // Compress by loop
        while (os.toByteArray().length / 1024 > maxSize) {
            // Clean up os
            os.reset();
            // interval 10
            options -= 10;
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, os);
        }

        bitmap.recycle();

        return os;
    }

    /**
     * 保存图片流到文件.
     */
    public static void saveBitmap(ByteArrayOutputStream os, String outPath) throws IOException {
        File f = new File(outPath);
        if (f.exists()) {
            final boolean isDelete = f.delete();
            if (isDelete) {
                LogUtils.d("delete ok!");
            }
        }

        // Generate compressed image file
        FileOutputStream fos = new FileOutputStream(outPath);
        fos.write(os.toByteArray());
        fos.flush();
        fos.close();
        os.flush();
        os.close();
    }

    /**
     * 保存图片对象到文件.
     */
    public static String saveBitmap(Bitmap bm, String url) {
        File f = new File(url);
        if (f.exists()) {
            final boolean isDelete = f.delete();
            if (isDelete) {
                LogUtils.d("delete ok!");
            }
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            bm.compress(Bitmap.CompressFormat.PNG, 80, out);
            out.flush();
            out.close();
            bm.recycle();
            return url;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 删除图片
     *
     * @param path
     */
    public static void deletePicture(String path) {
        FileUtil.RecursionDeleteFile(new File(path));
    }

    /**
     * 删除图片
     *
     * @param pathList
     */
    public static void deletePictures(List<String> pathList) {
        for (String path : pathList) {
            FileUtil.RecursionDeleteFile(new File(path));
        }
    }

    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }
        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void doTailorImageOfGlideView(Context context, ImageView imageView, String file,
                                                int imageSize, int w, int h) {
        Observable.just(new TailorImagePer(context, imageView, file, imageSize, w, h))
                .flatMap(new Function<TailorImagePer, ObservableSource<TailorImagePer>>() {
                    @Override
                    public Observable<TailorImagePer> apply(TailorImagePer tailorImagePer) {
                        Bitmap bitmapOrg = BitmapFactory.decodeFile(tailorImagePer.file);
                        //设置图片大小480*720
                        bitmapOrg = zoomImage(bitmapOrg, 480, 720);
                        try {
                            //压缩图片到60KB
                            ByteArrayOutputStream os = compressAndGenImage(bitmapOrg, 60);
                            String newFileName = getNewFileName(tailorImagePer.file);
                            saveBitmap(os, newFileName);
                            tailorImagePer.file = newFileName;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        return Observable.just(tailorImagePer);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<TailorImagePer>() {
                    @Override
                    public void accept(TailorImagePer tailorImagePer) throws Exception {
                        tailorImagePer.imageView.setTag(tailorImagePer.file);
                        displayDisk(tailorImagePer.context, tailorImagePer.file, tailorImagePer.imageView);
                    }
                });
    }

    private static String getNewFileName(String file) {
        if (file.contains(FB_IMAGE_NAME)) {
            return file;
        }
        StringBuilder sb = new StringBuilder(file);
        sb.insert(file.length() - 5, FB_IMAGE_NAME);
        LogUtils.e("新图片地址 = " + sb.toString());
        return sb.toString();
    }

    private static class TailorImagePer {
        Context context;
        ImageView imageView;
        String file;
        int imageSize;
        int w;
        int h;

        TailorImagePer(Context context, ImageView imageView,
                       String file, int imageSize, int w, int h) {
            this.context = context;
            this.imageView = imageView;
            this.file = file;
            this.imageSize = imageSize;
            this.w = w;
            this.h = h;
        }
    }

    public static RequestBody createRequestBody(String imageUrl) {
        return RequestBody.create(MediaType.parse("application/octet-stream"), new File(imageUrl));
    }

}
